package zouran.util;

import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.endpoint.UserSpecifiedEndpointBuilder;
import com.qcloud.cos.http.HttpMethodName;
import com.qcloud.cos.http.HttpProtocol;
import com.qcloud.cos.model.COSObject;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.region.Region;
import com.qcloud.cos.utils.IOUtils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;

/**
 * 腾讯云COS文件上传与下载工具包
 *
 * @author zouran
 * createDate：2024/8/4  20:18
 */
public class COSFileUtil {
    public static boolean used;
    private static String generalApiEndpoint;
    private static String serviceApiEndpoint;

    /**
     * @param used               是否开启
     * @param generalApiEndpoint 自定义源站域名
     * @param serviceApiEndpoint 代表列举存储桶列表时的域名，推荐填 service.cos.myqcloud.com
     */
    public static void init(boolean used, String generalApiEndpoint, String serviceApiEndpoint) {
        COSFileUtil.used = used;
        COSFileUtil.generalApiEndpoint = generalApiEndpoint;
        COSFileUtil.serviceApiEndpoint = serviceApiEndpoint;
    }

    public static COSClient creatCOSClient(String secretId, String secretKey, String regionName) {
        COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
        Region region = new Region(regionName);
        ClientConfig clientConfig = new ClientConfig(region);
        // 设置请求协议，推荐使用 https 协议
        clientConfig.setHttpProtocol(HttpProtocol.https);
        //若设置自定义源站域名时未上传 https 证书，则改为 clientConfig.setHttpProtocol(HttpProtocol.http);
        // 设置自定义的域名
        if (used) {
            UserSpecifiedEndpointBuilder endpointBuilder = new UserSpecifiedEndpointBuilder(generalApiEndpoint, serviceApiEndpoint);
            clientConfig.setEndpointBuilder(endpointBuilder);
        }
        return new COSClient(cred, clientConfig);
    }

    public static void put(InputStream inputStream, Integer size, String filePath, String secretId, String secretKey, String regionName, String bucketName) {
        COSClient cosClient = creatCOSClient(secretId, secretKey, regionName);
        ObjectMetadata objectMetadata = new ObjectMetadata();
        // 上传的流如果能够获取准确的流长度，则推荐一定填写 content-length
        // 如果确实没办法获取到，则下面这行可以省略，但同时高级接口也没办法使用分块上传了
        if (size != null)
            objectMetadata.setContentLength(size);
        cosClient.putObject(bucketName, filePath, inputStream, objectMetadata);
        cosClient.shutdown();
    }

    public static void put(File file, String filePath, String secretId, String secretKey, String regionName, String bucketName) {
        COSClient cosClient = creatCOSClient(secretId, secretKey, regionName);
        cosClient.putObject(bucketName, filePath, file);
        cosClient.shutdown();
    }

    public static byte[] get(String filePath, String secretId, String secretKey, String regionName, String bucketName) throws IOException {
        COSClient cosClient = creatCOSClient(secretId, secretKey, regionName);
        COSObject cosObject = cosClient.getObject(bucketName, filePath);
        InputStream cosObjectInput = cosObject.getObjectContent();
        byte[] bytes = IOUtils.toByteArray(cosObjectInput).clone();
        cosClient.shutdown();
        return bytes;
    }

    public static boolean check(String filePath, String secretId, String secretKey, String regionName, String bucketName) {
        COSClient cosClient = creatCOSClient(secretId, secretKey, regionName);
        boolean isExist;
        isExist = cosClient.doesObjectExist(bucketName, filePath);
        cosClient.shutdown();
        return isExist;
    }

    public static ObjectMetadata getObjectMetadata(String filePath, String secretId, String secretKey, String regionName, String bucketName) {
        COSClient cosClient = creatCOSClient(secretId, secretKey, regionName);
        ObjectMetadata objectMetadata = cosClient.getObjectMetadata(bucketName, filePath);
        ObjectMetadata object = objectMetadata.clone();
        cosClient.shutdown();
        return object;
    }

    /**
     * @param filePath 文件路径
     * @param time     签名有效时间
     * @param method   请求方法
     * @return 链接
     */
    public static String generatePresignedUrl(String filePath, Integer time, HttpMethodName method, String secretId, String secretKey, String regionName, String bucketName) {
        COSClient cosClient = creatCOSClient(secretId, secretKey, regionName);
        // 这里设置签名在半个小时后过期
        Date expirationDate = new Date(System.currentTimeMillis() + time * 60 * 1000);
        // 请求的 HTTP 方法，上传请求用 PUT，下载请求用 GET，删除请求用 DELETE
        URL url = cosClient.generatePresignedUrl(bucketName, filePath, expirationDate, method);
        cosClient.shutdown();
        return url.toString();
    }
}
